/*
$LastChangedBy: ssidek@gmail.com $
$LastChangedDate: 2014-06-07 05:37:38 +0000 (Sat, 07 Jun 2014) $
$Revision: 106 $

Description:

*/

import java.util.ArrayList;
import java.util.TreeSet;
import org.apache.commons.lang3.StringUtils;

public class Student {
	// Instance variables
	private String loginName;
	private TreeSet<Course> courseSet = new TreeSet<Course>(); 

	// Constructors
	
	/** 
	* Creates a student by filling in only the loginName.  Courses can be added via
	* the following methods:
	* (1) addCourses() - used if a list of course IDs is available for this student 
	* (representing courses this student is already registered for, obtained from 
	* StudentList.txt), or
	* (2) registerCourse() - used when the student registers for a course.
	*
	* @param loginName	login name of the student
	*/
	public Student(String loginName) {
		this.loginName  = loginName;
	}

	// Methods

	/** Returns the student's login name
	* @return Login name of the student
	*/
	public String getLogin() {
		return loginName;
	}

	/** 
	* Returns a TreeSet<Course> containing the courses for which the student is 
	* registered, sorted by course ID.
	*
	* @return Set of courses for which the student is registered
	*/
	public TreeSet<Course> getCourseSet() {
		return courseSet; 
	}

	/** 
	* Returns a string containing a comma-separated list of course IDs for this 
	* student, suitable for UI display or writing to StudentList.txt.  
	* If the student doesn't have any courses, the returned string is empty.
	* 
	* @return String containing courseIDs for which this student is registered
	*/
	public String getCourseIDs() {

		StringBuilder courseIDs = new StringBuilder("");
		if (this.courseSet.size() > 0) {
			Boolean firstCourse = true;
			for (Course c : courseSet) {
				if (!firstCourse) {
					courseIDs.append(",");
				}
				courseIDs.append(c.getID());
				firstCourse = false;
			}
		}
		
		return courseIDs.toString(); 
	}

	/** 
	* Returns the number of courses for which this student is registered.
	* 
	* @return Number of courses
	*/
	public int getCourseCount() {
		return this.courseSet.size();
	}

	/**
	* Adds a set of courses to a student, using the student's list of courseIDs and
	* matching them to the list of existing courses.  
	* Note, this does NOT register the student, it's assumed that the studentCourses
	* parameter represents courses the student is already registered for (obtained from
	* StudentList.txt).
	* 
	* @param studentCourses List of courseIDs, for which the student is registered
	* @param courseList List of Course objects defined for the system
	*/
	public void addCourses(ArrayList<String> studentCourses, 
		TreeSet<Course> courseList) {

		// For each courseID in the student's list...
		for (String courseID : studentCourses) {

			// Find the Course object with this ID.  When found, add the
			// Course object to this student's courseSet.
			for (Course c : courseList) {
				if (c.getID().equals(courseID)) {
					this.courseSet.add(c);
					break;
				}
			}
		}

		return;
	}

	/**
	* Adds this student to the specified course.  This method first registers
	* the student for the course, by updating the Course object.  If successful, 
	* the student's courseSet is updated.  
	* If the student is already registered for this course, or the course is already 
	* full, return value will be false.
	* 
	* @param aCourse The course for which the student should be registered.
	* @return true if successful, otherwise false
	*/
	public Boolean registerCourse(Course aCourse) {
		
		Boolean result = false;  // assume failure

		if (this.courseSet.contains(aCourse)) {
			// This course is already in the student's list
			System.out.println("Error, " + loginName + " has already registered for " +
				aCourse.getID());
		} else if (aCourse.isCourseFull()) {
			// This course is full
			System.out.println("Error, " + aCourse.getID() + " is full.");
		} else {
			System.out.println("Registering " + loginName + 
				" for " + aCourse.getID());
			result = (aCourse.registerStudent()); 
			if (result == true) {
				courseSet.add(aCourse);
			}
		}
		return result;	
	}

	/**
	* Removes this student from the specified course.  This method first unregisters
	* the student for the course, by updating the Course object.  If successful, 
	* the student's courseSet is updated.  
	* If the student isn't registered for this course, or the course is already 
	* empty, return value will be false.
	* 
	* @param aCourse The course for which the student should be unregistered.
	* @return true if successful, otherwise false
	*/
	public Boolean unregisterCourse(Course aCourse) {
		
		Boolean result = false;  // assume failure
		if (!this.courseSet.contains(aCourse)) {
			// The student isn't registered for this course 
			System.out.println("Error, " + loginName + " is not registered for " +
				aCourse.getID());
		} else if (aCourse.getCurrentEnrolled() == 0) {
			// This course has no students
			System.out.println("Error, " + aCourse.getID() + " has no students.");
		} else {
			System.out.println("Unregistering " + loginName + 
				" from " + aCourse.getID());
			result = (aCourse.unregisterStudent()); 
			if (result == true) {
				courseSet.remove(aCourse);
			}
		}
		return result;	
	}

	/**
	* Returns a multi-line string, suitable for UI display, containing the student's 
	* login name and a comma-separated list of course IDs.  This string format is NOT the
	* same as used in StudentList.txt file.
	* If this student doesn't have any courses, the course list
	* is displayed as "(empty)".
	* 
	* @return String identifying the student's login name and list of courses
	*/
	public String toString() {

		StringBuilder studentInfo = new StringBuilder("Login Name: " + loginName + "\n");
		studentInfo.append("Course List: ");
		studentInfo.append(getCourseIDs());
		if (StringUtils.endsWith(studentInfo.toString(), "Course List: ")) {
			studentInfo.append("(empty)");
		}

		studentInfo.append("\n");
		
		return studentInfo.toString(); 
	}

}
